package com.zzh.util.excel.utils;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.databind.ObjectMapper;

import com.zzh.util.excel.annotation.Export;
import com.zzh.util.excel.business.ExcelImportBusinessPrePo;
import com.zzh.util.excel.enums.ExportExcelClassEnumInterface;
import com.zzh.util.excel.listener.DataListener;
import com.zzh.util.excel.model.vo.ImportExcelResultVo;
import com.zzh.util.excel.registry.ExcelImportDateListRegistry;
import com.zzh.util.excel.registry.ExportExcelClassEnumRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.util.*;

public class ExcelUtil {

    public void exportExcel(HttpServletResponse response, String queryPo, ExportExcelClassEnumInterface classEnum)
            throws IllegalAccessException, InstantiationException, InvocationTargetException, IOException {
        ExportExcelClassEnumInterface exportExcelClassEnum = ExportExcelClassEnumRegistry.getEnum(classEnum.getCode());
        Class poClass = exportExcelClassEnum.getPoClass();
        Class serviceClass = exportExcelClassEnum.getServiceClass();

        Object service = SpringContextUtil.getBean(classEnum.getServiceClass());

        Object po = poClass.newInstance();

        ObjectMapper objectMapper = new ObjectMapper();

        Map<String, Object> map = objectMapper.readValue(queryPo, Map.class);

        Map<String, Object> queryPo_ = (Map<String, Object>) map.get("queryPo");
        Set<String> includeColumnFieldNames = new HashSet<>((Collection<String>) map.get("includeColumnFieldNames"));

        Field[] fields = poClass.getDeclaredFields();
        for (Field field:fields){
            field.setAccessible(true);
            if (queryPo_.containsKey(field.getName())){
                field.set(po,queryPo_.get(field.getName()));
            }
        }
        Method[] methods = serviceClass.getDeclaredMethods();

        for (Method method : methods) {
            if (method.isAnnotationPresent(Export.class)) {
                Object page = method.invoke(service, po);
                IPage result=(IPage)page;
                List<?> records = result.getRecords();
                ExcelUtil.exportExcel(records,classEnum.getTitle(),"",classEnum.getVoClass(),classEnum.getFileName(),response,includeColumnFieldNames);
            }
        }
    }


    public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response,Set<String> includeColumnFieldNames) throws IOException {

        // 设置响应头（强制浏览器下载）
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + ".xlsx", "UTF-8"));
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");

        // 通过response的输出流写入Excel
        EasyExcel.write(response.getOutputStream(), pojoClass)
                .includeColumnFieldNames(includeColumnFieldNames)
                .sheet(sheetName)
                .doWrite(list);
    }
    public static void templateExport(HttpServletResponse response,ExportExcelClassEnumInterface classEnum) throws IOException {
        exportExcel(new ArrayList<>(),"","",classEnum.getCreatePoClass(),classEnum.getFileName(),response,new HashSet<>());
    }

    public static ImportExcelResultVo templateImport(MultipartFile file, ExportExcelClassEnumInterface classEnum, ExcelImportBusinessPrePo po) throws IOException {
        EasyExcel.read(file.getInputStream(), classEnum.getCreatePoClass(), new DataListener(classEnum,po)).sheet().doRead();
        Integer fail = ExcelImportDateListRegistry.getFailData(po.getUuid()).size();
        Integer success = ExcelImportDateListRegistry.getSuccessData(po.getUuid()).size();
        return new ImportExcelResultVo().setTotalCount(fail+success)
                .setFailCount(fail).setSuccessCount(success);
    }

    public static void downloadFailData(ExportExcelClassEnumInterface classEnum, ExcelImportBusinessPrePo po, HttpServletResponse response) throws IOException {
        List<?> errorDataList = ExcelImportDateListRegistry.getFailData(po.getUuid());
        ExcelUtil.exportExcel(errorDataList,"","",classEnum.getCreatePoClass(),"导入失败数据",response,new HashSet<>());

    }

}
